package com.fivefu.core.gb28181.utils;

import com.fivefu.core.gb28181.listner.SipServerLayer;
import com.fivefu.core.gb28181.pojo.DeviceBean;
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.message.SIPRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.ListIterator;

@Component
public class SipMessageUtils {

    @Autowired
    private SipServerLayer sipServerLayer;

    //设备参数
    private String deviceID = "34020000001180000001";//设备编号

    private String deviceIP = "192.168.0.144";

//    private int devicePort = 37777;
//
//    private String deviceType = "tcp";//tcp
//
//    private int devicePort = 37778;

    private int devicePort = 5060;

    private String deviceType = "udp";//tcp

    //服务参数
    private String serviceID = "34020000002000000001";//服务编号

    private String serviceIP = "192.168.0.138";

    private int servicePort = 5060;

    /**
     * 创建sip公用表头
     * @param sipFactory
     * @param sipProvider
     * @param viaTag
     * @param fromTag
     * @param toTag
     * @param messageType
     * @return
     * @throws PeerUnavailableException
     * @throws ParseException
     * @throws InvalidArgumentException
     */
    public Request createSipHeader(DeviceBean bean, SipFactory sipFactory, SipProvider sipProvider, String viaTag, String fromTag, String toTag, String messageType) throws PeerUnavailableException, ParseException, InvalidArgumentException {
        SipURI requestURI = sipFactory.createAddressFactory().createSipURI(bean.getDeviceID(), bean.getDeviceIP() + ":" + bean.getDevicePort());
        //Via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader via = sipFactory.createHeaderFactory().createViaHeader(bean.getDeviceIP(), bean.getDevicePort(), bean.getDeviceType(), viaTag);
        viaHeaders.add(via);
        //From
        SipURI fromURI = sipFactory.createAddressFactory().createSipURI(serviceID, serviceIP + ":" + servicePort);
        Address fromAddress = sipFactory.createAddressFactory().createAddress(fromURI);
        FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
        //To
        Address toAddress = sipFactory.createAddressFactory().createAddress(requestURI);
        ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
        //Forward
        MaxForwardsHeader forwardsHeader = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
        //Cseq
        CSeqHeader cseqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, messageType);
        //CallIdHeader
        CallIdHeader callHeader = sipProvider.getNewCallId();
        Request request = sipFactory.createMessageFactory().createRequest(requestURI, messageType, callHeader, cseqHeader, fromHeader, toHeader, viaHeaders, forwardsHeader);
        if (messageType.equals(Request.INVITE)){
            //Contact
            request.addHeader(sipFactory.createHeaderFactory().createContactHeader(toAddress));
        }
        return request;
    }

    public ClientTransaction sendMessage(DeviceBean bean,String viaTag, String fromTag, String toTag, String content) throws PeerUnavailableException, ParseException, InvalidArgumentException, TransactionUnavailableException {
        /*SipFactory sipFactory = sipServerLayer.getSipFactory();

        SipURI requestURI = sipFactory.createAddressFactory().createSipURI(deviceID, deviceIP + ":" + devicePort);
        //Via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader via = sipFactory.createHeaderFactory().createViaHeader(deviceIP, devicePort, deviceType, viaTag);
        viaHeaders.add(via);
        //From
        SipURI fromURI = sipFactory.createAddressFactory().createSipURI(serviceID, serviceIP + ":" + servicePort);
        Address fromAddress = sipFactory.createAddressFactory().createAddress(fromURI);
        FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
        //To
        Address toAddress = sipFactory.createAddressFactory().createAddress(requestURI);
        ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
        //Forward
        MaxForwardsHeader forwardsHeader = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
        //Cseq
        CSeqHeader cseqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.MESSAGE);
        //CallIdHeader
        SipProvider sipProvider = null;
        if (deviceType.toUpperCase().equals("TCP")){
            sipProvider = sipServerLayer.getTcpProvider();
        }else{
            sipProvider = sipServerLayer.getUdpProvider();
        }
        CallIdHeader callHeader = sipProvider.getNewCallId();
        Request request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callHeader, cseqHeader, fromHeader, toHeader, viaHeaders, forwardsHeader);
        ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
        request.setContent(content, contentTypeHeader);
        System.out.println("request:" + request);

        ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);
        return clientTransaction;*/
        SipFactory sipFactory = sipServerLayer.getSipFactory();
        SipProvider sipProvider = null;
        if (bean.getDeviceType().toUpperCase().equals("TCP")){
            sipProvider = sipServerLayer.getTcpProvider();
        }else{
            sipProvider = sipServerLayer.getUdpProvider();
        }



        Request request = createSipHeader(bean,sipFactory, sipProvider, viaTag, fromTag, toTag, Request.MESSAGE);

        ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
        request.setContent(content, contentTypeHeader);
        System.out.println("request:" + request);

        ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);
        return clientTransaction;
    }

    public ClientTransaction sendInviteMessage(DeviceBean bean,String channelID,String viaTag, String fromTag, String toTag, String ssrc, String content) throws PeerUnavailableException, ParseException, InvalidArgumentException, TransactionUnavailableException {
        SipFactory sipFactory = sipServerLayer.getSipFactory();
        SipProvider sipProvider = null;
        if (bean.getDeviceType().toUpperCase().equals("TCP")){
            sipProvider = sipServerLayer.getTcpProvider();
        }else{
            sipProvider = sipServerLayer.getUdpProvider();
        }


        Request request = createSipHeader(bean,sipFactory, sipProvider, viaTag, fromTag, toTag, Request.INVITE);

        //Subject
        SubjectHeader subjectHeader = sipFactory.createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelID, ssrc, bean.getDeviceID(), 0));
        request.addHeader(subjectHeader);

        ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
        request.setContent(content, contentTypeHeader);
        System.out.println("request:" + request);

        ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);
        return clientTransaction;
    }

    public ServerTransaction ackRequest(RequestEvent requestEvent, Response response) throws SipException, InvalidArgumentException {
        ServerTransaction transaction = requestEvent.getServerTransaction();
        Request request = requestEvent.getRequest();
        if (transaction == null) {
            SipStackImpl stack = (SipStackImpl) sipServerLayer.getSipStack();
            transaction = (ServerTransaction) stack.findTransaction((SIPRequest)request,true);

            String deviceType = null;
            ListIterator viaHeaders = request.getHeaders(ViaHeader.NAME);
            while (viaHeaders.hasNext()){
                ViaHeader viaHeader = (ViaHeader) viaHeaders.next();
                deviceType = viaHeader.getTransport();
            }

            SipProvider sipProvider = null;
            if (deviceType.equals("TCP")){
                sipProvider = sipServerLayer.getUdpProvider();
            }else{
                sipProvider = sipServerLayer.getTcpProvider();
            }

            if (transaction == null){
                transaction = sipProvider.getNewServerTransaction(request);
            }
        }
        if (transaction != null){
//            // 添加Contact头
//            response.addHeader(request.getHeader(ContactHeader.NAME));
            // 添加Expires头
            response.addHeader(request.getExpires());
            System.out.println(response);
            transaction.sendResponse(response);
        }
        return transaction;
    }

}
